package com.yunxi.service.dubboService.impl.sto;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageInfo;
import com.yunxi.core.util.BeanTools;
import com.yunxi.core.web.DictConstant;
import com.yunxi.hubToBiz.pojo.HubProduceTracePlanVO;
import com.yunxi.model.order.PmsVehicleStock;
import com.yunxi.model.sto.StoManage;
import com.yunxi.model.sto.StoStockInPlan;
import com.yunxi.model.sto.StoStorageStaff;
import com.yunxi.model.sto.VehicleOffline;
import com.yunxi.sat.pojo.SatMessAddVO;
import com.yunxi.service.localService.CodeCreateService;
import com.yunxi.service.localService.sat.SatMessService;
import com.yunxi.service.localService.sto.*;
import com.yunxi.sto.pojo.*;
import com.yunxi.sto.service.StoStockInPlanDubboService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 车辆入库计划 服务实现类
 * </p>
 *
 * @author caoYong
 * @since 2019-05-14
 */
public class StoStockInPlanDubboServiceImpl implements StoStockInPlanDubboService {

    @Autowired
    @Qualifier(value = "stoStockInPlanServiceImpl")
    StoStockInPlanService stoStockInPlanService;

    @Autowired
    @Qualifier(value = "vehicleStockMServiceImpl")
    VehicleStockMService vehicleStockMService;

    @Autowired
    @Qualifier(value = "codeCreateServiceImpl")
    CodeCreateService codeCreateService;

    @Autowired
    VehicleOfflineService vehicleOfflineService;

    @Autowired
    @Qualifier(value = "stoStorageStaffServiceImpl")
    StoStorageStaffService stoStorageStaffService;

    @Autowired
    @Qualifier(value = "satMessServiceImpl")
    SatMessService satMessService;

    @Autowired
    @Qualifier(value = "stoChangeStorageServiceImpl")
    StoChangeStorageService stoChangeStorageService;

    @Autowired
    @Qualifier(value = "stoManageServiceImpl")
    StoManageService stoManageService;


    @Override
    public StoStockInPlanVO getById(String id)throws Exception {
        StoStockInPlanVO stoStockInPlanVO = stoStockInPlanService.getDetailById(id);
        if(stoStockInPlanVO != null){
            return stoStockInPlanVO;
        }
        else{
            throw new Exception("操作失败,无法根据主键id:"+id+"找到对应入库计划单!");
        }
    }

    @Override
    public void complete(StoStockScanVO stoStockScanVO) throws Exception {
        stoStockInPlanService.complete(stoStockScanVO);
    }

    @Override
    public void saveAndUpdate(StoStockInPlanVO stoStockInPlanVO) throws Exception {
        stoStockInPlanService.saveAndUpdate(stoStockInPlanVO);
    }

    @Override
    public void delAndReset(List<String> list, Integer isDel,String userId) throws Exception {
        stoStockInPlanService.delAndReset(list,isDel,userId);
    }

    /**
     * 下线生成入库计划
     * @param produceTracePlanVO 车辆生产跟踪VO
     */
    @Override
    public void addStockInPlan(HubProduceTracePlanVO produceTracePlanVO) throws Exception {
        /*StoStockInPlanVO stoStockInPlanVO = new StoStockInPlanVO();
        stoStockInPlanVO.setVin(produceTracePlanVO.getZvin());
        stoStockInPlanVO.setZordNo(produceTracePlanVO.getZordno());
        stoStockInPlanVO.setStockInType("1");
        stoStockInPlanVO.setBillCreateTime(new Date());
        stoStockInPlanVO.setPlanStockInDate(new Date());
        stoStockInPlanService.saveAndUpdate(stoStockInPlanVO);*/
    }

    @Override
    public PageInfo<StoStockInPlanResponseVO> findPageByVO(StoStockInPlanVO stoStockInPlanVO, Integer pageNum, Integer pageSize) throws InvocationTargetException, IllegalAccessException {
        PageInfo<StoStockInPlanResponseVO> pageInfo = stoStockInPlanService.findPageByVO(stoStockInPlanVO, pageNum, pageSize);
        /*List<StoStockInPlanResponseVO> list = pageInfo.getList();
        if(list != null && list.size() > 0){
            for (StoStockInPlanResponseVO vo : list){
                String ck = vo.getCk();
                String kq = vo.getKq();
                String kd = vo.getKd();
                String storageName = vo.getStorageName();
                if(StringUtil.isNotEmpty(ck) && StringUtil.isNotEmpty(kq) && StringUtil.isNotEmpty(kd) && StringUtil.isNotEmpty(storageName)){
                    vo.setStorageFullName(ck+"-"+kq+"-"+kd+"-"+storageName);
                }
            }
        }
        pageInfo.setList(list);*/
        return pageInfo;
    }

    /**
     * 逾期入库计划
     * @param pageNum
     * @param pageSize
     * @return
     * @throws Exception
     */
    @Override
    public PageInfo<StoStockInPlanLateVO> lateStockInPlan(StoStockInPlanLateVO stoStockInPlanLateVO, Integer pageNum, Integer pageSize) throws Exception {
        return stoStockInPlanService.lateStockInPlan(stoStockInPlanLateVO,pageNum,pageSize);
    }

    @Override
    public List<StoStockInPlanResponseVO> export(StoStockInPlanVO stoStockInPlanVO) throws Exception {
        return stoStockInPlanService.export(stoStockInPlanVO);
    }

    /**
     * 将车辆VIN码和车辆RFID绑定,并返回入库目标库位
     * @param stoStockScanVO
     * @return
     * @throws Exception
     */
    @Override
    public String bindVehicleRfid(StoStockScanVO stoStockScanVO) throws Exception {
        String storageCode = stoStockInPlanService.bindVehicleRfid(stoStockScanVO);
        return storageCode;
    }

    /**
     * 分配司机
     * @param stoStockInPlanDriverVO
     * @throws Exception
     */
    @Override
    public void setDriver(StoStockInPlanDriverVO stoStockInPlanDriverVO) throws Exception {
        StoStockInPlan stoStockInPlan = stoStockInPlanService.getById(stoStockInPlanDriverVO.getStockInPlanId());
        if(stoStockInPlan == null)throw new Exception("操作失败,无法根据主键id:"+stoStockInPlanDriverVO.getStockInPlanId()+"找到对应记录!");
        stoStockInPlan.setRfidNo(stoStockInPlanDriverVO.getRfidNo());
        stoStockInPlan.setRfidDate(new Date());
        stoStockInPlanService.saveOrUpdate(stoStockInPlan);

        //推送消息给司机
        QueryWrapper<StoStorageStaff> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("RFID",stoStockInPlanDriverVO.getRfidNo());
        StoStorageStaff stoStorageStaff = stoStorageStaffService.getOne(queryWrapper);
        if(stoStorageStaff != null){
            SatMessAddVO satMessAddVO = new SatMessAddVO();
            satMessAddVO.setType("入库");
            satMessAddVO.setInfo("有一个新的入库计划!");
            satMessAddVO.setSalesConsultantNo(stoStorageStaff.getStorageStaffPhone());
            satMessAddVO.setReceiveRoleCode(DictConstant.USER_ROLE_DRIVER);
            satMessService.pdaNewMess(satMessAddVO);
        }

    }

    /**
     * 开始入库
     * @param stoStockScanVO
     * @throws Exception
     */
    @Override
    public void beginStockIn(StoStockScanVO stoStockScanVO) throws Exception {
        stoStockInPlanService.beginStockIn(stoStockScanVO);
    }

    @Override
    public List<StoStockInOutReportListVO> stockInOutCount(String rfidNo) throws Exception {
        return stoStockInPlanService.stockInOutCount(rfidNo);
    }

    /**
     * 通过vin查询入库计划
     * @param vin
     * @return
     * @throws Exception
     */
    @Override
    public List<StoStockInPlanVO> planListByVin(String vin,String rfid) throws Exception {
        return stoStockInPlanService.planListByVin(vin,rfid);
    }

    /**
     * 通过RFID查询入库计划
     * @param rfid
     * @param partnerCode
     * @return
     * @throws Exception
     */
    @Override
    public List<StoStockInPlanVO> rfidPlan(String rfid, String partnerCode) throws Exception {
        QueryWrapper<StoStockInPlan> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("RFID_NO",rfid);
        queryWrapper.ne("BILL_STATE","2");
        queryWrapper.ne("BILL_STATE","3");
        List<StoStockInPlan> list = stoStockInPlanService.list(queryWrapper);
        List<StoStockInPlanVO> list1 = new ArrayList<>();
        if(list != null && list.size() > 0){
            list1 = BeanTools.copyListToList(list, StoStockInPlanVO.class);
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            for(int i = 0;i<list1.size();i++){
                Date planStockInDate = list.get(i).getPlanStockInDate();
                if(planStockInDate != null){
                    String format = simpleDateFormat.format(planStockInDate);
                    list1.get(i).setPlanStockInDate(format);
                }
            }
        }
        return list1;
    }

    /**
     * 退车入库
     * @param stoStockReturnInVO
     * @throws Exception
     */
    @Override
    @Transactional
    public void returnIn(StoStockReturnInVO stoStockReturnInVO) throws Exception {
        String vin = stoStockReturnInVO.getVin();
        String partnerCode = stoStockReturnInVO.getPartnerCode();
        if(StringUtils.isEmpty(vin) || StringUtils.isEmpty(partnerCode)){
            throw new Exception("操作失败,VIN码或渠道商代码为空!");
        }
        QueryWrapper<PmsVehicleStock> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("VIN",vin);
        PmsVehicleStock vehicleStock = vehicleStockMService.getOne(queryWrapper);
        vehicleStock.setPartnerCode(partnerCode);
        vehicleStock.setStorageStatus(1);
        //1.更新车辆所属渠道库存
        vehicleStockMService.saveOrUpdate(vehicleStock);
        //2.生成已完成入库的记录
        StoStockInPlan stoStockInPlan = new StoStockInPlan();
        stoStockInPlan.setVin(vin);
        String stockInNo = codeCreateService.createCode("SIP", 4);
        stoStockInPlan.setStockInPlanNo(stockInNo);
        stoStockInPlan.setBillState("2");//完成入库
        stoStockInPlan.setStockInType("3");//退货入库
        stoStockInPlan.setPlanStockInDate(new Date());
        stoStockInPlan.setStockInDate(new Date());
        stoStockInPlan.setBillCreateTime(new Date());
        stoStockInPlanService.saveOrUpdate(stoStockInPlan);
        //3.更新车辆下线数据库存状态
        QueryWrapper<VehicleOffline> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("VIN",vin);
        VehicleOffline vehicleOffline = vehicleOfflineService.getOne(queryWrapper1);
        if(vehicleOffline != null){
            vehicleOffline.setStorageStatus(1);
            vehicleOfflineService.saveOrUpdate(vehicleOffline);
        }
    }

    /**
     * 导入新增入库计划
     * @param list
     * @throws Exception
     */
    @Override
    public void imoprtPlan(List<StoStockInPlanImportVO> list) throws Exception {
        if(list == null || list.size() <= 0)throw new Exception("操作失败,导入数据为空!");
        for(StoStockInPlanImportVO vo : list){
            String stockInType = vo.getStockInType();//入库类型
            String manualReason = vo.getManualReason();//手动入库原因
            String stockInDate = vo.getStockInDate();//计划入库日期
            String vin = vo.getVin();//VIN码
            String remark = vo.getRemark();//其他事项说明

            //校验数据
            if(StringUtils.isEmpty(stockInDate) || StringUtils.isEmpty(vin))throw new Exception("操作失败,计划入库日期或VIN码不能为空!");
            //转换入库类型中文为字典
            if(StringUtils.isEmpty(stockInType)){
                vo.setStockInType("1");//如果没导入入库类型,则给默认值 下线入库
            }
            else {
                transferStockInType(vo, stockInType);
            }
            //判断计划入库日期格式
            try {
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                simpleDateFormat.parse(stockInDate);
            }
            catch (ParseException e){
                throw new Exception("操作失败,计划入库日期格式需要为yyyy-MM-dd!");
            }

            StoStockInPlanVO stoStockInPlanVO = new StoStockInPlanVO();
            stoStockInPlanVO.setStockInType(vo.getStockInType());
            stoStockInPlanVO.setManualReason(manualReason);
            stoStockInPlanVO.setPlanStockInDate(stockInDate);
            stoStockInPlanVO.setVin(vin);
            stoStockInPlanVO.setRemark(remark);
            //自动分配库位
            VehiclePdiBillVO vehiclePdiBillVO = new VehiclePdiBillVO();
            List<StoChangeStorageVinListVO> stoChangeStorageVinListVOS = stoChangeStorageService.storageList(vehiclePdiBillVO);
            if(stoChangeStorageVinListVOS != null || stoChangeStorageVinListVOS.size() > 0){
                for(StoChangeStorageVinListVO changeVO : stoChangeStorageVinListVOS){
                    String isPositionFrozen = changeVO.getIsPositionFrozen();
                    String storageCode = changeVO.getStorageLocation();
                    if(StringUtils.isEmpty(isPositionFrozen) || isPositionFrozen.equals("0")){
                        //将库位代码写入入库计划单
                        stoStockInPlanVO.setStorageCode(storageCode);
                        break;
                    }
                }
            }
            stoStockInPlanService.saveAndUpdate(stoStockInPlanVO);
        }
    }

    /**
     * 开始充电
     * @param stoStockScanVO
     * @throws Exception
     */
    @Override
    public void inCharge(StoStockScanVO stoStockScanVO) throws Exception {
        //根据VIN码查询未完成的入库计划
        QueryWrapper<StoStockInPlan> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("VIN",stoStockScanVO.getVin());
        //排除完成,作废,充电中的单据
        queryWrapper.ne("BILL_STATE","2");
        queryWrapper.ne("BILL_STATE","3");
        queryWrapper.ne("BILL_STATE","4");
        List<StoStockInPlan> list = stoStockInPlanService.list(queryWrapper);
        if(list == null || list.size() <= 0)throw new Exception("操作失败,无法根据VIN码:"+stoStockScanVO.getVin()+"找到未完成的入库计划!");
        for(StoStockInPlan bo : list){
            bo.setBillState("4");
            bo.setChargeUser(stoStockScanVO.getUpdateBy());
            bo.setBeginChargeDate(new Date());
            stoStockInPlanService.saveOrUpdate(bo);
        }
    }

    /**
     * 完成充电
     * @param stoStockScanVO
     * @throws Exception
     */
    @Override
    public void outCharge(StoStockScanVO stoStockScanVO) throws Exception {
        //根据VIN码查询充电中的入库计划
        QueryWrapper<StoStockInPlan> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("VIN",stoStockScanVO.getVin());
        queryWrapper.eq("BILL_STATE","4");
        List<StoStockInPlan> list = stoStockInPlanService.list(queryWrapper);
        if(list == null || list.size() <= 0)throw new Exception("操作失败,无法根据VIN码:"+stoStockScanVO.getVin()+"找到充电中的入库计划!");
        for(StoStockInPlan bo : list){
            bo.setBillState("5");
            bo.setEndChargeUser(stoStockScanVO.getUpdateBy());
            bo.setEndChargeDate(new Date());
            stoStockInPlanService.saveOrUpdate(bo);
        }
    }

    /**
     * 转换入库类型中文为字典
     * @param vo
     * @param stockInType
     */
    private void transferStockInType(StoStockInPlanImportVO vo, String stockInType) {
        switch (stockInType){
            case DictConstant.CN_STOCK_IN_XXRK:
                vo.setStockInType("1");
                break;
            case DictConstant.CN_STOCK_IN_DBRK:
                vo.setStockInType("2");
                break;
            case DictConstant.CN_STOCK_IN_THRK:
                vo.setStockInType("3");
                break;
            case DictConstant.CN_STOCK_IN_SXRK:
                vo.setStockInType("4");
                break;
            case DictConstant.CN_STOCK_IN_HCRK:
                vo.setStockInType("5");
                break;
            case DictConstant.CN_STOCK_IN_JCRK:
                vo.setStockInType("6");
                break;
            case DictConstant.CN_STOCK_IN_HWCRK:
                vo.setStockInType("7");
                break;
            case DictConstant.CN_STOCK_IN_JJCRK:
                vo.setStockInType("11");
                break;
            case DictConstant.CN_STOCK_IN_YDDBCRK:
                vo.setStockInType("12");
                break;
            case DictConstant.CN_STOCK_IN_QXJHRK:
                vo.setStockInType("13");
                break;
            case DictConstant.CN_STOCK_IN_XHLYRK:
                vo.setStockInType("14");
                break;
            default:
                vo.setStockInType("1");//入库类型不规则,默认赋值为下线入库
                break;
        }
    }
}
